package jmine.tec.rpc.common.serialization;

import java.util.ArrayList;
import java.util.List;

import jmine.tec.rpc.common.provider.RestServiceProvider;
import jmine.tec.rpc.common.serialization.json.JSONApacheIntValuedEnumConverter;
import jmine.tec.rpc.common.serialization.json.JSONApacheStringValuedEnumConverter;
import jmine.tec.rpc.common.serialization.json.JSONArrayClassConverter;
import jmine.tec.rpc.common.serialization.json.JSONArrayConverter;
import jmine.tec.rpc.common.serialization.json.JSONBeanConverter;
import jmine.tec.rpc.common.serialization.json.JSONBooleanConverter;
import jmine.tec.rpc.common.serialization.json.JSONClassConverter;
import jmine.tec.rpc.common.serialization.json.JSONConverter;
import jmine.tec.rpc.common.serialization.json.JSONConverterStrategy;
import jmine.tec.rpc.common.serialization.json.JSONDateConverter;
import jmine.tec.rpc.common.serialization.json.JSONEnumConverter;
import jmine.tec.rpc.common.serialization.json.JSONIntegerConverter;
import jmine.tec.rpc.common.serialization.json.JSONLazyRepresentationConverter;
import jmine.tec.rpc.common.serialization.json.JSONListConverter;
import jmine.tec.rpc.common.serialization.json.JSONLongConverter;
import jmine.tec.rpc.common.serialization.json.JSONMapConverter;
import jmine.tec.rpc.common.serialization.json.JSONNullObjectConverter;
import jmine.tec.rpc.common.serialization.json.JSONNumberConverter;
import jmine.tec.rpc.common.serialization.json.JSONSerializer;
import jmine.tec.rpc.common.serialization.json.JSONSetConverter;
import jmine.tec.rpc.common.serialization.json.JSONStringConverter;
import jmine.tec.rpc.common.serialization.json.JSONThrowableConverter;
import jmine.tec.rpc.common.serialization.json.JSONTimeConverter;
import jmine.tec.rpc.common.serialization.json.JSONTimestampConverter;
import jmine.tec.test.Builder;

/**
 * Builder for Serializer
 * 
 * @author lundberg
 */
public class SerializerBuilder implements Builder<Serializer> {

    private RestServiceProvider provider;

    private List<JSONConverterStrategy> strategies = new ArrayList<JSONConverterStrategy>();

    /**
     * {@inheritDoc}
     */
    public Serializer build() {
        JSONConverter converter = new JSONConverter(this.strategies.toArray(new JSONConverterStrategy[this.strategies.size()]));
        converter.setProvider(this.provider);
        try {
            converter.afterPropertiesSet();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
        JSONSerializer serializer = new JSONSerializer();
        serializer.setConverter(converter);
        return serializer;
    }

    /**
     * @return SerializerBuilder
     * @param provider provider
     */
    public static SerializerBuilder aLazyCapableSerializer(RestServiceProvider provider) {
        SerializerBuilder builder = new SerializerBuilder();
        builder.provider = provider;
        builder.with(new JSONNullObjectConverter());
        builder.with(new JSONStringConverter());
        builder.with(new JSONNumberConverter());
        builder.with(new JSONBooleanConverter());
        builder.with(new JSONListConverter());
        builder.with(new JSONSetConverter());
        builder.with(new JSONMapConverter());
        builder.with(new JSONDateConverter());
        builder.with(new JSONClassConverter());
        builder.with(new JSONArrayClassConverter());
        builder.with(new JSONArrayConverter());
        builder.with(new JSONEnumConverter());
        builder.with(new JSONIntegerConverter());
        builder.with(new JSONLongConverter());
        builder.with(new JSONThrowableConverter());
        builder.with(new JSONLazyRepresentationConverter());
        builder.with(new JSONApacheIntValuedEnumConverter());
        builder.with(new JSONApacheStringValuedEnumConverter());
        builder.with(new JSONBeanConverter());
        return builder;
    }

    /**
     * @return SerializerBuilder
     */
    public static SerializerBuilder aSerializer() {
        SerializerBuilder builder = new SerializerBuilder();
        builder.with(new JSONNullObjectConverter());
        builder.with(new JSONStringConverter());
        builder.with(new JSONNumberConverter());
        builder.with(new JSONBooleanConverter());
        builder.with(new JSONListConverter());
        builder.with(new JSONMapConverter());
        builder.with(new JSONDateConverter());
        builder.with(new JSONTimeConverter());
        builder.with(new JSONTimestampConverter());
        builder.with(new JSONArrayClassConverter());
        builder.with(new JSONClassConverter());
        builder.with(new JSONArrayConverter());
        builder.with(new JSONEnumConverter());
        builder.with(new JSONIntegerConverter());
        builder.with(new JSONLongConverter());
        builder.with(new JSONThrowableConverter());
        builder.with(new JSONApacheIntValuedEnumConverter());
        builder.with(new JSONApacheStringValuedEnumConverter());
        builder.with(new JSONBeanConverter());
        return builder;
    }

    /**
     * @param strategy strategy
     * @return this
     */
    public SerializerBuilder with(JSONConverterStrategy strategy) {
        this.strategies.add(strategy);
        return this;
    }
}
